<?php


namespace app\src\redis;

use app\src\adlist\adlist;
use app\src\dict\dict;

/**
 *
 *
 * User: Implement hdjahs@qq.com
 * Date: 2020/12/1 3:16
 */
class redisServer
{

    const REDIS_RUN_ID_SIZE = 40;

    const REDIS_BINDADDR_MAX = 60;

    const REDIS_CLIENT_LIMIT_NUM_CLASSES = 3;

    const ANET_ERR_LEN = 256;

    const REDIS_OPS_SEC_SAMPLES = 16;

    public $configfile; // 配置文件的绝对路径

    public $hz; //每秒调用的次数

    public $db; // 数据库

    public $commands; // 命令表（受到 rename 配置选项的作用）

    public $orig_commands; // 命令表（无 rename 配置选项的作用）

    public $lruclock; // 最近一次使用时钟

    public $shutdown_asap; // 关闭服务器的标识

    public $activerehashing; // 在执行 serverCron() 时进行渐进式 rehash

    public $requirepass; // 是否设置了密码

    public $pidfile; // PID 文件

// serverCron() 函数的运行次数计数器
    public $cronloops;

    // 本服务器的 RUN ID
    public $runid = [self::REDIS_RUN_ID_SIZE + 1];

    // 服务器是否运行在 SENTINEL 模式
    public $sentinel_mode;


    /* Networking */

    // TCP 监听端口
    public $port;

    public $tcp_backlog;

    // 地址
    public $bindaddr = [self::REDIS_BINDADDR_MAX];

    // 地址数量
    public $bindaddr_count;

    // UNIX 套接字
    public $unixsocket;

    public $unixsocketperm;

    // 描述符
    public $ipfd = [self::REDIS_BINDADDR_MAX]; /* TCP socket file descriptors */

    // 描述符数量
    public $ipfd_count;

    // UNIX 套接字文件描述符
    public $sofd;                   /* Unix socket file descriptor */

    public $cfd = [self::REDIS_BINDADDR_MAX];/* Cluster bus listening socket */

    public $cfd_count;              /* Used slots in cfd[] */

    // 一个链表，保存了所有客户端状态结构
    public $clients;              /* List of active clients */

    // 链表，保存了所有待关闭的客户端
    public $clients_to_close;     /* Clients to close asynchronously */

    // 链表，保存了所有从服务器，以及所有监视器
    public $slaves;    /* List of slaves and MONITORs */

    public $monitors;

    // 服务器的当前客户端，仅用于崩溃报告
    public $current_client; /* Current client, only used on crash report */

    public $clients_paused;         /* True if clients are currently paused */

    public $clients_pause_end_time; /* Time when we undo clients_paused */

    // 网络错误
    public $neterr = [self::ANET_ERR_LEN];   /* Error buffer for anet.c */

    // MIGRATE 缓存
    public $migrate_cached_sockets;/* MIGRATE cached sockets */


    /* RDB / AOF loading information */

    // 这个值为真时，表示服务器正在进行载入
    public $loading;                /* We are loading data from disk if true */

    // 正在载入的数据的大小
    public $loading_total_bytes;

    // 已载入数据的大小
    public $loading_loaded_bytes;

    // 开始进行载入的时间
    public $loading_start_time;

    public $loading_process_events_interval_bytes;

    /* Fast pointers to often looked up command */

    // 常用命令的快捷连接
    public $delCommand;

    public $multiCommand;

    public $lpushCommand;

    public $lpopCommand;

    public $rpopCommand;

    /* Fields used only for stats */

    // 服务器启动时间
    public $stat_starttime;          /* Server start time */

    // 已处理命令的数量
    public $stat_numcommands;     /* Number of processed commands */

    // 服务器接到的连接请求数量
    public $stat_numconnections;  /* Number of connections received */

    // 已过期的键数量
    public $stat_expiredkeys;     /* Number of expired keys */

    // 因为回收内存而被释放的过期键的数量
    public $stat_evictedkeys;     /* Number of evicted keys (maxmemory) */

    // 成功查找键的次数
    public $stat_keyspace_hits;   /* Number of successful lookups of keys */

    // 查找键失败的次数
    public $stat_keyspace_misses; /* Number of failed lookups of keys */

    // 已使用内存峰值
    public $stat_peak_memory;        /* Max used memory record */

    // 最后一次执行 fork() 时消耗的时间
    public $stat_fork_time;       /* Time needed to perform latest fork() */

    // 服务器因为客户端数量过多而拒绝客户端连接的次数
    public $stat_rejected_conn;   /* Clients rejected because of maxclients */

    // 执行 full sync 的次数
    public $stat_sync_full;       /* Number of full resyncs with slaves. */

    // PSYNC 成功执行的次数
    public $stat_sync_partial_ok; /* Number of accepted PSYNC requests. */

    // PSYNC 执行失败的次数
    public $stat_sync_partial_err;/* Number of unaccepted PSYNC requests. */

    /* slowlog */

    // 保存了所有慢查询日志的链表
    public $slowlog;                  /* SLOWLOG list of commands */

    // 下一条慢查询日志的 ID
    public $slowlog_entry_id;     /* SLOWLOG current entry ID */

    // 服务器配置 slowlog-log-slower-than 选项的值
    public $slowlog_log_slower_than; /* SLOWLOG time limit (to get logged) */

    // 服务器配置 slowlog-max-len 选项的值
    public $slowlog_max_len;     /* SLOWLOG max number of items logged */

    public $resident_set_size;       /* RSS sampled in serverCron(). */

    // 最后一次进行抽样的时间
    public $ops_sec_last_sample_time; /* Timestamp of last sample (in ms) */

    // 最后一次抽样时，服务器已执行命令的数量
    public $ops_sec_last_sample_ops;  /* numcommands in last sample */

    // 抽样结果
    public $ops_sec_samples = [self::REDIS_OPS_SEC_SAMPLES];

    // 数组索引，用于保存抽样结果，并在需要时回绕到 0
    public $ops_sec_idx;

    /* Configuration */

    // 日志可见性
    public $verbosity;                  /* Loglevel in redis.conf */

    // 客户端最大空转时间
    public $maxidletime;                /* Client timeout in seconds */

    // 是否开启 SO_KEEPALIVE 选项
    public $tcpkeepalive;               /* Set SO_KEEPALIVE if non-zero. */

    public $active_expire_enabled;      /* Can be disabled for testing purposes. */

    public $client_max_querybuf_len; /* Limit for client query buffer length */

    public $dbnum;                      /* Total number of configured DBs */

    public $daemonize;                  /* True if running as a daemon */

    // 客户端输出缓冲区大小限制
    // 数组的元素有 REDIS_CLIENT_LIMIT_NUM_CLASSES 个
    // 每个代表一类客户端：普通、从服务器、pubsub，诸如此类
    public $client_obuf_limits = [self::REDIS_CLIENT_LIMIT_NUM_CLASSES];

    /* AOF persistence */

    // AOF 状态（开启/关闭/可写）
    public $aof_state;                  /* REDIS_AOF_(ON|OFF|WAIT_REWRITE) */

    // 所使用的 fsync 策略（每个写入/每秒/从不）
    public $aof_fsync;                  /* Kind of fsync() policy */

    public $aof_filename;             /* Name of the AOF file */

    public $aof_no_fsync_on_rewrite;    /* Don't fsync if a rewrite is in prog. */

    public $aof_rewrite_perc;           /* Rewrite AOF if % growth is > M and... */

    public $aof_rewrite_min_size;     /* the AOF file is at least N bytes. */

    // 最后一次执行 BGREWRITEAOF 时， AOF 文件的大小
    public $aof_rewrite_base_size;    /* AOF size on latest startup or rewrite. */

    // AOF 文件的当前字节大小
    public $aof_current_size;         /* AOF current size. */

    public $aof_rewrite_scheduled;      /* Rewrite once BGSAVE terminates. */

    // 负责进行 AOF 重写的子进程 ID
    public $aof_child_pid;            /* PID if rewriting process */

    // AOF 重写缓存链表，链接着多个缓存块
    public $aof_rewrite_buf_blocks;   /* Hold changes during an AOF rewrite. */

    // AOF 缓冲区
    public $aof_buf;      /* AOF buffer, written before entering the event loop */

    // AOF 文件的描述符
    public $aof_fd;       /* File descriptor of currently selected AOF file */

    // AOF 的当前目标数据库
    public $aof_selected_db; /* Currently selected DB in AOF */

    // 推迟 write 操作的时间
    public $aof_flush_postponed_start; /* UNIX time of postponed AOF flush */

    // 最后一直执行 fsync 的时间
    public $aof_last_fsync;            /* UNIX time of last fsync() */

    public $aof_rewrite_time_last;   /* Time used by last AOF rewrite run. */

    // AOF 重写的开始时间
    public $aof_rewrite_time_start;  /* Current AOF rewrite start time. */

    // 最后一次执行 BGREWRITEAOF 的结果
    public $aof_lastbgrewrite_status;   /* REDIS_OK or REDIS_ERR */

    // 记录 AOF 的 write 操作被推迟了多少次
    public $aof_delayed_fsync;  /* delayed AOF fsync() counter */

    // 指示是否需要每写入一定量的数据，就主动执行一次 fsync()
    public $aof_rewrite_incremental_fsync;/* fsync incrementally while rewriting? */

    public $aof_last_write_status;      /* REDIS_OK or REDIS_ERR */

    public $aof_last_write_errno;       /* Valid if aof_last_write_status is ERR */
    /* RDB persistence */

    // 自从上次 SAVE 执行以来，数据库被修改的次数
    public $dirty;                /* Changes to DB from the last save */

    // BGSAVE 执行前的数据库被修改次数
    public $dirty_before_bgsave;  /* Used to restore dirty on failed BGSAVE */

    // 负责执行 BGSAVE 的子进程的 ID
    // 没在执行 BGSAVE 时，设为 -1
    public $rdb_child_pid;            /* PID of RDB saving child */

    public $saveparams;   /* Save points array for RDB */

    public $saveparamslen;              /* Number of saving points */

    public $rdb_filename;             /* Name of RDB file */

    public $rdb_compression;            /* Use compression in RDB? */

    public $rdb_checksum;               /* Use RDB checksum? */

    // 最后一次完成 SAVE 的时间
    public $lastsave;                /* Unix time of last successful save */

    // 最后一次尝试执行 BGSAVE 的时间
    public $lastbgsave_try;          /* Unix time of last attempted bgsave */

    // 最近一次 BGSAVE 执行耗费的时间
    public $rdb_save_time_last;      /* Time used by last RDB save run. */

    // 数据库最近一次开始执行 BGSAVE 的时间
    public $rdb_save_time_start;     /* Current RDB save start time. */

    // 最后一次执行 SAVE 的状态
    public $lastbgsave_status;          /* REDIS_OK or REDIS_ERR */

    public $stop_writes_on_bgsave_err;  /* Don't allow writes if can't BGSAVE */

    /* Propagation of commands in AOF / replication */
    public $also_propagate;    /* Additional command to propagate. */

    /* Logging */
    public $logfile;                  /* Path of log file */

    public $syslog_enabled;             /* Is syslog enabled? */

    public $syslog_ident;             /* Syslog ident */

    public $syslog_facility;            /* Syslog facility */

    /* Replication (master) */
    public $slaveseldb;                 /* Last SELECTed DB in replication output */

    // 全局复制偏移量（一个累计值）
    public $master_repl_offset;   /* Global replication offset */

    // 主服务器发送 PING 的频率
    public $repl_ping_slave_period;     /* Master pings the slave every N seconds */

    // backlog 本身
    public $repl_backlog;             /* Replication backlog for partial syncs */

    // backlog 的长度
    public $repl_backlog_size;    /* Backlog circular buffer size */

    // backlog 中数据的长度
    public $repl_backlog_histlen; /* Backlog actual data length */

    // backlog 的当前索引
    public $repl_backlog_idx;     /* Backlog circular buffer current offset */

    // backlog 中可以被还原的第一个字节的偏移量
    public $repl_backlog_off;

    // backlog 的过期时间
    public $repl_backlog_time_limit;

    // 距离上一次有从服务器的时间
    public $repl_no_slaves_since;

    // 是否开启最小数量从服务器写入功能
    public $repl_min_slaves_to_write;   /* Min number of slaves to write. */

    // 定义最小数量从服务器的最大延迟值
    public $repl_min_slaves_max_lag;    /* Max lag of <count> slaves to write. */

    // 延迟良好的从服务器的数量
    public $repl_good_slaves_count;     /* Number of slaves with lag <= max_lag. */

    /* Replication (slave) */
    // 主服务器的验证密码
    public $masterauth;               /* AUTH with this password with master */

    // 主服务器的地址
    public $masterhost;               /* Hostname of master */

    // 主服务器的端口
    public $masterport;                 /* Port of master */

    // 超时时间
    public $repl_timeout;               /* Timeout after N seconds of master idle */

    // 主服务器所对应的客户端
    public $master;     /* Client that is master for this slave */

    // 被缓存的主服务器，PSYNC 时使用
    public $cached_master; /* Cached master to be reused for PSYNC. */

    public $repl_syncio_timeout; /* Timeout for synchronous I/O calls */

    // 复制的状态（服务器是从服务器时使用）
    public $repl_state;          /* Replication status if the instance is a slave */

    // RDB 文件的大小
    public $repl_transfer_size; /* Size of RDB to read from master during sync. */

    // 已读 RDB 文件内容的字节数
    public $repl_transfer_read; /* Amount of RDB read from master during sync. */

    // 最近一次执行 fsync 时的偏移量
    // 用于 sync_file_range 函数
    public $repl_transfer_last_fsync_off; /* Offset when we fsync-ed last time. */

    // 主服务器的套接字
    public $repl_transfer_s;     /* Slave -> Master SYNC socket */

    // 保存 RDB 文件的临时文件的描述符
    public $repl_transfer_fd;    /* Slave -> Master SYNC temp file descriptor */

    // 保存 RDB 文件的临时文件名字
    public $repl_transfer_tmpfile; /* Slave-> master SYNC temp file name */

    // 最近一次读入 RDB 内容的时间
    public $repl_transfer_lastio; /* Unix time of the latest read, for timeout */

    public $repl_serve_stale_data; /* Serve stale data when link is down? */

    // 是否只读从服务器？
    public $repl_slave_ro;          /* Slave is read only? */

    // 连接断开的时长
    public $repl_down_since; /* Unix time at which link with master went down */

    // 是否要在 SYNC 之后关闭 NODELAY ？
    public $repl_disable_tcp_nodelay;   /* Disable TCP_NODELAY after SYNC? */

    // 从服务器优先级
    public $slave_priority;             /* Reported in INFO and used by Sentinel. */

    // 本服务器（从服务器）当前主服务器的 RUN ID
    public $repl_master_runid = [self::REDIS_RUN_ID_SIZE + 1];  /* Master run id for PSYNC. */

    // 初始化偏移量
    public $repl_master_initial_offset;         /* Master PSYNC offset. */

    /* Replication script cache. */
    // 复制脚本缓存
    // 字典
    public $repl_scriptcache_dict;        /* SHA1 all slaves are aware of. */

    // FIFO 队列
    public $repl_scriptcache_fifo;        /* First in, first out LRU eviction. */

    // 缓存的大小
    public $repl_scriptcache_size;          /* Max number of elements. */

    /* Synchronous replication. */
    public $clients_waiting_acks;         /* Clients waiting in WAIT command. */

    public $get_ack_from_slaves;            /* If true we send REPLCONF GETACK. */
    /* Limits */
    public $maxclients;                 /* Max number of simultaneous clients */

    public $maxmemory;   /* Max number of memory bytes to use */

    public $maxmemory_policy;           /* Policy for key eviction */

    public $maxmemory_samples;          /* Pricision of random sampling */

    /* Blocked clients */
    public $bpop_blocked_clients; /* Number of clients blocked by lists */

    public $unblocked_clients; /* list of clients to unblock before next loop */

    public $ready_keys;        /* List of readyList structures for BLPOP & co */

    public $sort_desc;

    public $sort_alpha;

    public $sort_bypattern;

    public $sort_store;

    /* Zip structure config, see redis.conf for more information  */
    public $hash_max_ziplist_entries;

    public $hash_max_ziplist_value;

    public $list_max_ziplist_entries;

    public $list_max_ziplist_value;

    public $set_max_intset_entries;

    public $zset_max_ziplist_entries;

    public $zset_max_ziplist_value;

    public $hll_sparse_max_bytes;

    public $unixtime;        /* Unix time sampled every cron cycle. */

    public $mstime;       /* Like 'unixtime' but with milliseconds resolution. */

    /* Pubsub */
    // 字典，键为频道，值为链表
    // 链表中保存了所有订阅某个频道的客户端
    // 新客户端总是被添加到链表的表尾
    public $pubsub_channels;  /* Map channels to list of subscribed clients */

    // 这个链表记录了客户端订阅的所有模式的名字
    public $pubsub_patterns;  /* A list of pubsub_patterns */

    public $notify_keyspace_events;

    /* Cluster */
    public $cluster_enabled;      /* Is cluster enabled? */

    public $cluster_node_timeout; /* Cluster node timeout. */

    public $cluster_configfile; /* Cluster auto-generated config file name. */

    public $cluster;  /* State of the cluster */

    public $cluster_migration_barrier;

    // Lua 环境
    public $lua; /* The Lua interpreter. We use just one for all clients */

    // 复制执行 Lua 脚本中的 Redis 命令的伪客户端
    public $lua_client;   /* The "fake client" to query Redis from Lua */

    // 当前正在执行 EVAL 命令的客户端，如果没有就是 NULL
    public $lua_caller;   /* The client running EVAL right now, or NULL */

    // 一个字典，值为 Lua 脚本，键为脚本的 SHA1 校验和
    public $lua_scripts;         /* A dictionary of SHA1 -> Lua scripts */

    // Lua 脚本的执行时限
    public $lua_time_limit;  /* Script timeout in milliseconds */

    // 脚本开始执行的时间
    public $lua_time_start;  /* Start time of script, milliseconds time */

    // 脚本是否执行过写命令
    public $lua_write_dirty;

    // 脚本是否执行过带有随机性质的命令
    public $lua_random_dirty;

    // 脚本是否超时
    public $lua_timedout;

    // 是否要杀死脚本
    public $lua_kill;         /* Kill the script if true. */

    /* Assert & bug reporting */

    public $assert_failed;

    public $assert_file;

    public $assert_line;

    public $bug_report_start; /* True if bug report header was already logged. */

    public $watchdog_period;  /* Software watchdog period in ms. 0 = off */

    public function __construct()
    {
        $this->db = new redisDb();
        $this->commands = new dict();
        $this->orig_commands = new dict();
        $this->clients = new adlist();
        $this->clients_to_close = new adlist();
        $this->slaves = new adlist();
        $this->monitors = new adlist();
        $this->current_client = new redisClient();
        $this->migrate_cached_sockets = new dict();
        $this->delCommand = new redisCommand();
        $this->multiCommand = new redisCommand();
        $this->lpushCommand = new redisCommand();
        $this->lpopCommand = new redisCommand();
        $this->rpopCommand = new redisCommand();
        $this->slowlog = new adlist();
        $this->saveparams = new saveparam();
        $this->also_propagate = new redisOpArray();
        $this->master = new redisClient();
        $this->cached_master = new redisClient();
        $this->repl_scriptcache_dict = new dict();
        $this->repl_scriptcache_fifo = new adlist();
        $this->clients_waiting_acks = new adlist();
        $this->unblocked_clients = new adlist();
        $this->ready_keys = new adlist();
        $this->pubsub_channels = new dict();
        $this->pubsub_patterns = new adlist();
        $this->cluster = new clusterState();
        $this->lua_client = new redisClient();
        $this->lua_caller = new redisClient();
        $this->lua_scripts = new dict();

    }

}
